ClarityViz

Pipeline: .img -> histogram .nii -> graph represented as csv -> graph as graphml -> plotly

To run:

Step 1:

First, run the following. This takes the .img, generates the localeq histogram as an nii file, gets the nodes and edges as a csv and converts the csv into a graphml


In [ ]:
python runclarityviz.py --token Fear199Coronal --file-type img --source-directory /cis/project/clarity/data/clarity/isoCoronal

Step 2:

Then run this. This just converts the graphml into a plotly


In [ ]:
python runclarityviz.py --token Fear199Coronal --plotly yes

Results


In [ ]:
Starting pipeline for Fear199.img
Generating Histogram...
FINISHED GENERATING HISTOGRAM
Loading: Fear199/Fear199localeq.nii
Image Loaded: Fear199/Fear199localeq.nii
FINISHED LOADING NII
Coverting to points...
token=Fear199
total=600735744
max=255.000000
threshold=0.300000
sample=0.500000
(This will take couple minutes)
Above threshold=461409948
Samples=230718301
Finished
FINISHED GETTING POINTS

In [ ]:
~/clarityviztesting/Fear199Coronal$ ls
Fear199Coronal.csv	  Fear199Coronal.graphml     Fear199Coronal.nodes.csv
Fear199Coronal.edges.csv  Fear199Coronallocaleq.nii  Fear199Coronalplotly.html

Code

runclarityviz.py:


In [3]:
from clarityviz import clarityviz
import ...

def get_args():
    parser = argparse.ArgumentParser(description="Description")

    parser.add_argument("--token", type=str, required=True, help="The token.")
    parser.add_argument("--file-type", type=str, required=False, help="The file type.")
    parser.add_argument("--source-directory", type=str, required=False,
                        help="Optional setting of the source directory.")
    parser.add_argument("--plotly", type=str, required=False, help="Optional method to generate the plotly graphs.")
    parser.add_argument("--generate-nii-from-csv", type=str, required=False, help="script to generate nii")

    args = parser.parse_args()

    return args


def main():
    print('ayyooooo')
    args = get_args()

    if args.plotly == 'yes':
        ## Type in the path to your csv file here
        thedata = np.genfromtxt(args.token + '/' + args.token + '.csv',
            delimiter=',', dtype='int', usecols = (0,1,2), names=['a','b','c'])

        trace1 = go.Scatter3d(
            x = thedata['a'],
            y = thedata['b'],
            z = thedata['c'],
            mode='markers',
            marker=dict(
                size=1.2,
                color='purple',                # set color to an array/list of desired values
                colorscale='Viridis',   # choose a colorscale
                opacity=0.15
            )
        )

        data = [trace1]
        layout = go.Layout(
            margin=dict(
                l=0,
                r=0,
                b=0,
                t=0
            )
        )

        fig = go.Figure(data=data, layout=layout)
        print args.token + "plotly"
        plotly.offline.plot(fig, filename= args.token + "/" + args.token + "plotly.html")
    else:
        print('Starting pipeline for %s' % (args.token + '.' + args.file_type))
        if args.source_directory == None:
            c = clarityviz(args.token)
        else:
            c = clarityviz(args.token, args.source_directory)

        if args.file_type == 'img':
            #c.loadEqImg()
            c.generateHistogram()
            print('FINISHED GENERATING HISTOGRAM')
            c.loadNiiImg()
            print('FINISHED LOADING NII')
        elif args.file_type == 'nii':
            c.loadNiiImg()
            print('FINISHED LOADING NII')

        c.imgToPoints(0.3, 0.5)
        print("FINISHED GETTING POINTS")

        c.savePoints()

        c.plot3d()
        print("FINISHED PLOT3D")

        c.graphmlconvert()
        print("FINISHED GRAPHMLCONVERT")

if __name__ == "__main__":
    main()


  File "<ipython-input-3-e4f212d51a9a>", line 2
    import ...
             ^
SyntaxError: invalid syntax

clarityviz.py


In [ ]:
def generateHistogram(self):
        print('Generating Histogram...')
        if self._source_directory == None:
            path = self._token + '.img'
        else:
            path = self._source_directory + "/" + self._token + ".img"

        im = nib.load(path)

        im = im.get_data()
        img = im[:,:,:]

        shape = im.shape
        #affine = im.get_affine()

        x_value = shape[0]
        y_value = shape[1]
        z_value = shape[2]

        #####################################################

        imgflat = img.reshape(-1)

        #img_grey = np.array(imgflat * 255, dtype = np.uint8)

        #img_eq = exposure.equalize_hist(img_grey)

        #new_img = img_eq.reshape(x_value, y_value, z_value)
        #globaleq = nib.Nifti1Image(new_img, np.eye(4))

        ######################################################

        #clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))

        img_grey = np.array(imgflat * 255, dtype = np.uint8)
        #threshed = cv2.adaptiveThreshold(img_grey, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 0)

        cl1 = clahe.apply(img_grey)

        #cv2.imwrite('clahe_2.jpg',cl1)
        #cv2.startWindowThread()
        #cv2.namedWindow("adaptive")
        #cv2.imshow("adaptive", cl1)
        #cv2.imshow("adaptive", threshed)
        #plt.imshow(threshed)

        localimgflat = cl1 #cl1.reshape(-1)

        newer_img = localimgflat.reshape(x_value, y_value, z_value)
        localeq = nib.Nifti1Image(newer_img, np.eye(4))
        nib.save(localeq, self._token + '/' + self._token + 'localeq.nii')

In [ ]:
def loadGeneratedNii(self, path=None, info=False):
        path = self._token + '/' + self._token + 'localeq.nii'
        print("Loading: %s"%(path))

        #pathname = path+self._token+".nii"
        img = nib.load(path)
        if info:
            print(img)
        #self._img = img.get_data()[:,:,:,0]
        self._img = img.get_data()
        self._shape = self._img.shape
        self._max = np.max(self._img)
        print("Image Loaded: %s"%(path))
        return self

In [ ]:
def imgToPoints(self, threshold=0.1, sample=0.5, optimize=True):
        """Method to extract points data from the img file."""
        if not 0 <= threshold < 1:
            raise ValueError("Threshold should be within [0,1).")
        if not 0 < sample <= 1:
            raise ValueError("Sample rate should be within (0,1].")
        if self._img is None:
            raise ValueError("Img haven't loaded, please call loadImg() first.")

        total = self._shape[0]*self._shape[1]*self._shape[2]
        print("Coverting to points...\ntoken=%s\ntotal=%d\nmax=%f\nthreshold=%f\nsample=%f"\
               %(self._token,total,self._max,threshold,sample))
        print("(This will take couple minutes)")
        # threshold
        filt = self._img > threshold * self._max
        x, y, z = np.where(filt)
        v = self._img[filt]
        if optimize:
            self.discardImg()
        v = np.int16(255*(np.float32(v)/np.float32(self._max)))
        l = v.shape
        print("Above threshold=%d"%(l))
        # sample
        if sample < 1.0:
            filt = np.random.random(size=l) < sample
            x = x[filt]
            y = y[filt]
            z = z[filt]
            v = v[filt]
        self._points = np.vstack([x,y,z,v])
        self._points = np.transpose(self._points)
        print("Samples=%d"%(self._points.shape[0]))
        print("Finished")
        return self

In [ ]:
def plot3d(self, infile = None):
        """Method for plotting the Nodes and Edges"""
        filename = ""
        points_file = None
        if infile == None:
            points_file = self._points
            filename = self._token
        else:
            self.loadInitCsv(infile)
            infile = self._infile
            filename = self._filename

        # points is an array of arrays
        points = self._points
        outpath = self._token + '/'
        nodename = outpath + filename + '.nodes.csv'
        edgename = outpath + filename + '.edges.csv'

        with open(nodename, 'w') as nodefile:
            with open(edgename, 'w') as edgefile:
                for ind in range(len(points)):
                    #temp = points[ind].strip().split(',')
                    temp = points[ind]
                    x = temp[0]
                    y = temp[1]
                    z = temp[2]
                    v = temp[3]
                    radius = 18
                    nodefile.write("s" + str(ind + 1) + "," + str(x) + "," + str(y) + "," + str(z) + "\n")
                    for index in range(ind + 1, len(points)):
                        tmp = points[index]
                        distance = math.sqrt(math.pow(int(x) - int(tmp[0]), 2) + math.pow(int(y) - int(tmp[1]), 2) + math.pow(int(z) - int(tmp[2]), 2))
                        if distance < radius:
                                edgefile.write("s" + str(ind + 1) + "," + "s" + str(index + 1) + "\n")
                self._nodefile = nodefile
                self._edgefile = edgefile

In [ ]:
def graphmlconvert(self, nodefilename = None, edgefilename = None):
        """Method for extracting the data to a graphml file, based on the node and edge files"""
        nodefile = None
        edgefile = None

        # If no nodefilename was entered, used the Clarity object's nodefile
        if nodefilename == None:
            #nodefile = self._nodefile
            #nodefile = open(self._nodefile, 'r')

            self.loadNodeCsv(self._token + "/" + self._token + ".nodes.csv")
            nodefile = self._nodefile
        else:
            self.loadNodeCsv(nodefilename)
            nodefile = self._nodefile

        # If no edgefilename was entered, used the Clarity object's edgefile
        if edgefilename == None:
            #edgefile = self._edgefile
            #edgefile = open(self._edgefile, 'r')

            self.loadEdgeCsv(self._token + "/" + self._token + ".edges.csv")
            edgefile = self._edgefile
        else:
            self.loadEdgeCsv(edgefilename)
            edgefile = self._edgefile

        # Start writing to the output graphml file
        path = self._token + "/" + self._token + ".graphml"
        with open(path, 'w') as outfile:
            outfile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
            outfile.write("<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\n")
            outfile.write("         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
            outfile.write("         xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\n")
            outfile.write("         http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n")

            outfile.write("  <key id=\"d0\" for=\"node\" attr.name=\"attr\" attr.type=\"string\"/>\n")
            outfile.write("  <key id=\"e_weight\" for=\"edge\" attr.name=\"weight\" attr.type=\"double\"/>\n")
            outfile.write("  <graph id=\"G\" edgedefault=\"undirected\">\n")

            for line in nodefile:
                 if len(line) == 0:
                     continue
                 line = line.strip().split(',')
                 outfile.write("    <node id=\"" + line[0] + "\">\n")
                 outfile.write("      <data key=\"d0\">[" + line[1] + ", " + line[2] + ", " + line[3] +"]</data>\n")
                 outfile.write("    </node>\n")
            
            for line in edgefile:
                 if len(line) == 0:
                     continue
                 line = line.strip().split(',')
                 outfile.write("    <edge source=\"" + line[0] + "\" target=\"" + line[1] + "\">\n")
                 outfile.write("      <data key=\"e_weight\">1</data>\n")
                 outfile.write("    </edge>\n")

            outfile.write("  </graph>\n</graphml>")

In [ ]:
def graphmlToPlotly(self, path):
        ## Type in the path to your csv file here
        thedata = np.genfromtxt('../data/points/localeq.csv', delimiter=',', dtype='int', usecols = (0,1,2), names=['a','b','c'])

        trace1 = go.Scatter3d(
            x = thedata['a'],
            y = thedata['b'],
            z = thedata['c'],
            mode='markers',
            marker=dict(
                size=1.2,
                color='purple',                # set color to an array/list of desired values
                colorscale='Viridis',   # choose a colorscale
                opacity=0.15
            )
        )

        data = [trace1]
        layout = go.Layout(
            margin=dict(
                l=0,
                r=0,
                b=0,
                t=0
            )
        )

        fig = go.Figure(data=data, layout=layout)
        print "localeq"
        plotly.offline.plot(fig, filename= "localeq")